package h5

import (
	. "chess_platform/internal/common"
	"chess_platform/models/client"
	"chess_platform/models/h5"
	"fmt"
	"github.com/astaxie/beego/orm"
	"time"
)

//[h5]金钱
type CashController struct {
	GrantController
}

func (b *CashController) URLMapping() {
	b.Mapping("ListChildCash", b.ListChildCash)
	b.Mapping("ListMonth", b.ListMonth)
	b.Mapping("ListDetail", b.ListDetail)
	b.Mapping("Cash", b.Cash)
	b.Mapping("RestCash", b.RestCash)
	b.Mapping("BankInfo", b.BankInfo)
	b.Mapping("UpdateBank", b.UpdateBank)
	b.Mapping("Withdraw", b.Withdraw)
	b.Mapping("WithdrawRate", b.WithdrawRate)
	b.Mapping("ListWithdraw", b.ListWithdraw)
}

// @Title 代理(一级及二级)提成列表(首页中展示,因为二级代理产生的收益)
// @Description 代理(一级及二级)提成列表(首页中展示,因为二级代理产生的收益)
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Success 0 {object} []common.CashRecord
// @router /list-child-cash [post]
func (b *CashController) ListChildCash() {
	var p ListParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	if b.Level == Level1 {
		//一级代理提成列表(首页中展示,因为二级代理产生的收益)
		cr, count, err := h5.ListChildCash(p, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}

		//查找二级代理或玩家(本级玩家直充产生的提成)
		field := []string{"nickname", "head_img_url"}
		for _, v := range cr {
			if v.UserType == Agent {
				u, err := h5.SpecifyUserInfoById(v.ChildId, field)
				if err != nil {
					LogH5.Error(b.DatabaseError(err.Error()))
					return
				}
				if u != nil {
					v.Nickname = u.Nickname
					v.HeadImgUrl = u.HeadImgUrl
				} else {
					LogH5.Warning("h5_user里user表没有代理:%d,而h5里h5_cash_record里有", v.ChildId)
				}
			} else if v.UserType == Player {
				u, err := client.QueryUserInfoById(v.ChildId)
				if err != nil {
					LogH5.Error(b.DatabaseError(err.Error()))
					return
				}
				//if u != nil {
				v.Nickname = u.Nickname
				v.HeadImgUrl = u.ImageUrl
				//} else {
				//	LogH5.Warning("client里user表没有玩家:%d,而h5里h5_cash_record里有", v.ChildId)
				//}
			}
		}
		b.Res.Data = cr
		b.Res.Count = count
		b.ResponseSuccess()
		return
	} else {
		//二级代理提成列表(首页中展示)
		cr, count, err := h5.ListLevel2Cash(p, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		//查找玩家
		for _, v := range cr {
			u, err := client.QueryUserInfoById(v.ChildId)
			if err != nil {
				LogH5.Error(b.DatabaseError(err.Error()))
				return
			}
			v.Nickname = u.Nickname
			v.HeadImgUrl = u.ImageUrl
		}
		b.Res.Data = cr
		b.Res.Count = count
		b.ResponseSuccess()
		return
	}

}

// @Title 金钱流水账(按月分)
// @Description 金钱流水账(按月分)
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Success 0 {object} []h5.CashRecord
// @router /list-month [post]
func (b *CashController) ListMonth() {
	var p ListParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	cr, count, err := h5.ListMonth(p, b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	b.Res.Data = cr
	b.Res.Count = count
	b.ResponseSuccess()
}

// @Title 金钱流水账(每月详细帐单)
// @Description 金钱流水账(每月详细帐单)
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Param   month        body   int     true       "月份,1801表示2018年1月"
// @Success 0 {object} []h5.CashRecord
// @router /list-detail [post]
func (b *CashController) ListDetail() {
	var p ListCashParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	cr, count, err := h5.ListDetail(p, b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	b.Res.Data = cr
	b.Res.Count = count
	b.ResponseSuccess()
}

// @Title 统计累计收入，昨日收入，可提现
// @Description 统计累计收入，昨日收入，可提现
// @Success 0 {object} common.StatCash
// @Failure 400
// @router /cash [post]
func (b *CashController) Cash() {
	ac, err := h5.StatAgentCash(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = ac
	b.ResponseSuccess()
}

// @Title 可提现
// @Description 可提现
// @Success 0 {string} rest_cash 可提现金额
// @Failure 400
// @router /rest-cash [post]
func (b *CashController) RestCash() {
	ac, err := h5.RestCash(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = ac
	b.ResponseSuccess()
}

// @Title 获取银行卡信息
// @Description 获取银行卡信息
// @Success 0 {object} h5.AgentBank 银行卡信息
// @Failure 400 {string} 成功时返回 mutable  当月是否可修改，1-是，0-否
// @Failure 401 {string} 成功时返回 count    是否有提现记录，大于1-是，0-否
// @router /bank-info [post]
func (b *CashController) BankInfo() {
	ab, count, err := h5.AgentBankById(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if ab == nil {
		b.Res.Code = ErrNoData
		b.Res.Msg = MsgErrNoData
		b.Response()
		return
	}
	if !IsCurrentMonth(ab.CreateTime) {
		ab.Mutable = 1 //1-表示本月可修改，0-表示不可修改, 默认是0
	}
	data := map[string]interface{}{
		"count":     count, //表示有无记录,大于1表示有提现记录
		"bank_info": ab,
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 更新银行卡信息(同时也是新增)
// @Description 更新银行卡信息(同时也是新增)
// @Param   name            body    string  true      "户名"
// @Param   bank_name      	body    string  true      "开户行名字(工商银行，中国银行)"
// @Param   province        body    string  true      "开户行所在省"
// @Param   city            body    string  true      "开户行所在市"
// @Param   card_num        body    string  true      "银行帐号"
// @Param   branch          body    string  true      "银行支行"
// @Success 0 {string} 状态码
// @Failure 399
// @router /update-bank [post]
func (b *CashController) UpdateBank() {
	var p AgentBank
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.MinSize(p.Name, 2, "Name").Message("名字长度2-16")
	b.Valid.MaxSize(p.Name, 16, "Name").Message("名字长度2-16")
	b.Valid.MatchChinese(p.Name, "name").Message("")
	b.Valid.Required(p.BankName, "bank_name").Message("请输入开户行名")
	b.Valid.Required(p.Province, "province").Message("请输入开户行所在省")
	b.Valid.Required(p.City, "city").Message("请输入开户行所在市")
	b.Valid.Required(p.CardNum, "card_num").Message("请输入银行帐号")
	b.Valid.Required(p.Branch, "branch").Message("请输入银行支行")
	if !b.VerifyParamsError() {
		return
	}
	ab, _, err := h5.AgentBankById(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	data := map[string]interface{}{
		"uid":         b.Uid,
		"name":        p.Name,
		"bank_name":   p.BankName,
		"province":    p.Province,
		"city":        p.City,
		"card_num":    p.CardNum,
		"branch":      p.Branch,
		"create_time": time.Now().Unix(),
	}
	if ab == nil { //doesn't exist, we should new one
		_, err := h5.NewAgentBank(data)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}

	} else { //exist update bank info
		//首先判断上次更新银行卡号是否为当月，如果是不能更新，
		if IsCurrentMonth(ab.CreateTime) {
			b.Res.Code = ErrAgentBankUpdate
			b.Res.Msg = MsgErrAgentBankUpdate
			b.Response()
			return
		}
		_, err := h5.UpdateAgentBank(data, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}

	}
	b.ResponseSuccess()
}

// @Title 提现
// @Description 提现
// @Param   amount body   int     true       "提现金额,乘以100回传"
// @Success 0 {string} 状态码
// @router /withdraw [post]
func (b *CashController) Withdraw() {
	//时间限制：周一到周五，一天可以提现一次
	if !IsWorkday() {
		b.ResponseFail("提现时间为周一至周五")
		return
	}
	field := []string{"is_withdraw"}
	u, err := h5.SpecifyUserInfoById(b.Uid, field)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if u.IsWithdraw == 0 {
		b.ResponseFail("您暂时不能提现,请联系客服")
		return
	}

	type Params struct {
		Amount int64 `json:"amount"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}

	//获取后台配置最小提现金额
	miniAmount, err := h5.RuleByType(RuleMiniWithdrawAmount)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if miniAmount.Id == 0 {
		LogH5.Error(b.SystemError("未配置最小提现金额,请配置"))
		return
	}
	amount := miniAmount.Amount
	if amount == 0 {
		amount = 100
	}
	msg := fmt.Sprintf("最小提现金额:%v元", amount/100)
	b.Valid.Min(p.Amount, int(amount), "amount").Message(msg)
	if !b.VerifyParamsError() {
		return
	}

	//提现之前先检查有没有银行卡
	ab, _, err := h5.AgentBankById(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if ab == nil { //没有填写过银行卡
		b.Res.Code = ErrNotFound
		b.Res.Msg = "请先填写银行卡信息"
		b.Response()
		return

	}

	o := orm.NewOrm()
	o.Using(DBChessCenter)
	o.Begin()
	defer o.Rollback()
	//首先判断下提现款够不够提现以及能否达到最小提现金额
	cc, err := h5.CardCashById(b.Uid, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if cc.Uid == 0 {
		o.Rollback()
		LogH5.Error(b.DatabaseError(fmt.Sprintf("代理用户ID:%v,在h5_card_cash表不存在", b.Uid)))
		return
	}
	if IsToday(cc.WithdrawTime) {
		o.Rollback()
		b.ResponseFail("一天只能提现一次")
		return
	}

	if cc.Amount < p.Amount {
		o.Rollback()
		b.Res.Code = ErrCashNotEnough
		b.Res.Msg = MsgErrCashNotEnough
		b.Response()
		return
	}

	//一提现立即减去提现金额,即先冻结了这些钱，如果审核失败了就返回这些钱
	n, err := h5.UpdateCash(-p.Amount, b.Uid, true, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	//TODO:要做事件日志
	if n == 0 {
		o.Rollback()
		b.ResponseFail("提现失败,请联系客服")
		LogH5.Warning(fmt.Sprintf("代理:%d提现失败,"+
			"可能代理在h5_cash_card里没数据或token解析出来的uid错误", b.Uid))
		return
	}
	//金额减少记录
	cr := map[string]interface{}{
		"agent_id":    b.Uid,
		"type":        CashWithdraw,
		"amount":      -p.Amount,
		"month":       CurrentYearMonth(),
		"create_time": time.Now().Unix(),
	}
	_, err = h5.NewCashRecord(cr, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	//提现费率
	serviceCharge, tax, err := h5.WithdrawRate(p.Amount)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	wr := map[string]interface{}{
		"agent_id":      b.Uid,
		"amount":        p.Amount,
		"server_charge": serviceCharge,
		"tax":           tax,
		"real_income":   p.Amount - tax - serviceCharge,
		"status":        WithdrawApproving,
		"create_time":   time.Now().Unix(),
	}
	//提现记录
	_, err = h5.NewWithdrawRecord(wr, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()
	b.ResponseSuccess()
}

// @Title 提现费率(手续费,税)
// @Description 提现费率(手续费,税)
// @Param   amount body   int     true       "提现金额"
// @Success 0 {string}
// @router /withdraw-rate [post]
func (b *CashController) WithdrawRate() {
	type Params struct {
		Amount int64 `json:"amount"`
	}
	var p Params
	err := b.Unmarshal(&p)
	if err != nil {
		b.DecodeParamsError(err)
		return
	}
	serverCharge, tax, err := h5.WithdrawRate(p.Amount)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	data := map[string]interface{}{
		"server_charge": serverCharge,
		"tax":           tax,
		"real_income":   p.Amount - serverCharge - tax,
	}
	b.Res.Data = data
	b.ResponseSuccess()

}

// @Title 提现记录
// @Description 提现记录
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Success 0 {object} []common.WithdrawRecord
// @router /list-withdraw [post]
func (b *CashController) ListWithdraw() {
	var p ListParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	cr, count, err := h5.ListWithdraw(p, b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	b.Res.Data = cr
	b.Res.Count = count
	b.ResponseSuccess()
}
